package com.itcoon.transform.inject;

import com.itcoon.transform.base.exception.InjectException;
import com.itcoon.transform.base.utils.TransformServiceUtils;
import com.itcoon.transform.base.definition.InjectDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * @author Miaoxia Yu
 * @date 2020-10-28
 */
public class InjectHandler {

    private static final Logger log = LoggerFactory.getLogger(InjectHandler.class);

    public InjectDefinition.InjectInfo support(Method targetMethod, List<InjectDefinition.InjectInfo> injectInfos) {
        String expectAttribute = TransformServiceUtils.formatDataValue(targetMethod.getName());
        Optional<InjectDefinition.InjectInfo> injectInfoOp = injectInfos.stream().filter(injectInfo -> injectInfo.getAttribute().equals(expectAttribute)).findAny();
        return injectInfoOp.orElse(null);
    }

    public Object handle(Class<?> targetClass, InjectDefinition.InjectInfo injectInfo, Object value) {
        Object injectMode = injectInfo.getInjectMode();
        value = injectInfo.getAttributeSource() == null ? value : injectInfo.getAttributeSource();
        try {
            if (injectMode != null) {
                if (injectMode instanceof Supplier) {
                    Supplier<?> supplier = (Supplier<?>) injectMode;
                    return supplier.get();
                } else if (injectMode instanceof Function) {
                    Function function = (Function) injectMode;
                    return function.apply(value);
                }
                throw new InjectException(String.format("injectMode is unSupported, referer attribute#%s.%s", targetClass.getSimpleName(), injectInfo.getAttribute()));
            }
        }catch (Exception e){
            log.error("[Transform4j] - can not inject {}, the reason: {}", targetClass.getName(), e.getMessage());
            log.error(e.getMessage(), e);
            throw new InjectException(e.getMessage());
        }
        return value;
    }
}
